/*
仿照Linux实现工厂模式
1.降低OTDR产品耦合度，
2.


2021.7.25 by Menglong Wu
*/
#include <autoconfig.h>
#include <stdio.h>
#include <string.h>
#include "port.h"
#include "fpga-common.h"
#include "fpga-private.h"
#include "port.h"


// char *pmagic = MAGIC_FPGA_IF;

#define MAX_IF (40)
struct fpga_if fpga_iface[MAX_IF] = { 0 };

struct fpga_if if_head = { NULL };


// .pfun_fpga_open = com_fpga_open,

// .pfun_fpga_open = fpga_open, \
// .pfun_fpga_close = fpga_close, \
// .pfun_alive = com_fpga_alive, \

// extern int fpga_open(char *device, struct fpga_dev **dev,
// 			      unsigned long ispeed);
//                   {

//                   }
// int fpga_read_otdr_data(
// 		struct fpga_dev *dev,
// 		unsigned char *  otdr_data,
// 		unsigned long    len)
// {
// 	printf("%s()\r\n", __FUNCTION__);
// 	return 0;
// }

int none_set_gpio(struct fpga_dev *dev, int io, int val)
{
    return 0;
}

int none_get_gpio(struct fpga_dev *dev, int io, int *val)
{
    return 0;
}


static struct fpga_if com_if = {
    DEFAULT_FPGA_IF,
    .name          = "this-common",
    .pfun_set_gpio = none_set_gpio,
    .pfun_get_gpio = none_get_gpio,
};

#if 0
static struct fpga_if abc2 = {
	DEFAULT_FPGA_IF,
	// .pfun_read_frame = fpga_read_otdr_data2,
	.name = "this-abc2",
	.a    = 0x2a,
	.b    = 0x2b,
	.a    = 0x21b,
};
// static struct fpga_if abc3 = {
// 	.name            = "this-abc3",
// 	.a               = 0x3a,
// 	.b               = 0x3b,
// 	.a               = 0x31a,
// 	.pfun_read_frame = fpga_read_otdr_data3,
// };

static struct fpga_if abc4 = {
	.name = "this-abc4",
	.a    = 0x4a,
	.b    = 0x4b,
};
#endif

int fpga_if_register(struct fpga_if *interface)
{
    int i;
    for (i = 0; i < MAX_IF; i++) {
	if (fpga_iface[i].name &&
	    strcmp(interface->name, fpga_iface[i].name) == 0) {
	    printf("接口已经存在\r\n");
	    return -1;
	}
    }
    for (i = 0; i < MAX_IF; i++) {
	if (fpga_iface[i].name == NULL) {
	    break;
	}
    }
    // TODO 校验各个回调函数是否有效，正式程序可以不用
    fpga_if_check(interface);
    memcpy(&fpga_iface[i], interface, sizeof(struct fpga_if));
    return 0;
}

int fpga_if_unregister(char *name)
{
    int i;
    for (i = 0; i < MAX_IF; i++) {
	if (fpga_iface[i].name && strcmp(name, fpga_iface[i].name) == 0)
	{
	    fpga_iface[i].name = NULL;
	    // printf("成功删除接口\r\n");
	    return -1;
	}
    }
}

void fpga_if_check(struct fpga_if *interface)
{
    if (NULL == interface->pfun_start) {
	printf("pfun_start接口未定义\r\n");
    }
    if (NULL == interface->pfun_read_frame) {
	printf("pfun_read_frame接口未定义\r\n");
    }
    if (NULL == interface->pfun_isfinish) {
	printf("pfun_isfinish接口未定义\r\n");
    }
    if (NULL == interface->pfun_version) {
	printf("pfun_version接口未定义\r\n");
    }
    if (NULL == interface->pfun_dump) {
	printf("pfun_dump接口未定义\r\n");
    }
    if (NULL == interface->pfun_stop) {
	printf("pfun_stop接口未定义\r\n");
    }
    if (NULL == interface->pfun_set_gpio) {
	printf("pfun_set_gpio接口未定义\r\n");
    }
    if (NULL == interface->pfun_get_gpio) {
	printf("pfun_get_gpio接口未定义\r\n");
    }
}

struct fpga_if *fpga_if_append(char *name)
{
    // assert(name != NULL);

    int find = 0;
    int i;
    for (i = 0; i < MAX_IF; i++) {
	if (fpga_iface[i].name && strcmp(name, fpga_iface[i].name) == 0)
	{
	    fpga_if_check(&fpga_iface[i]);
	    return &fpga_iface[i];
	}
    }
    printf("接口[%s]不存在\r\n", name);
    return NULL;
}

#if 0

struct fpga_if abcd = { .name = "asfd" };

volatile int __fpga_if_start __attribute__((section(".fpga_if_start"))) = 0;
SECTION_FPGA_IF(head, "imhead", &if_head);
volatile int __fpga_if_end __attribute__((section(".fpga_if_end"))) = 0;
SECTION_FPGA_IF(ABC2, "abc2", &abc2);
SECTION_FPGA_IF(ABC3, "abc3", &abc3);


void init()
{
	struct section_type *pstart, *pend;

	if (&__fpga_if_start < &__fpga_if_end) {
		pstart = &__fpga_if_start;
		pend   = &__fpga_if_end;
	}
	else {
		pstart = &__fpga_if_end;
		pend   = &__fpga_if_start;
	}

	printf("__fpga_if_start %x\r\n", &__fpga_if_start);
	printf("__fpga_if_end %x\r\n", &__fpga_if_end);

	// pstart = &__fpga_if_ABC;

	printf("__fpga_if_abc %x\r\n", &__fpga_if_head);

	// pstart++;
	pstart = &__fpga_if_head;
	// printf("pstart %x\r\n", pstart);

	// while(pstart->type == MAGIC_FPGA_IF) {
	// printf("sizeof %x\r\n", sizeof(struct section_type ));
	// while (pstart < pend) {
	//     if (strcmp(pstart->type, MAGIC_FPGA_IF) == 0) {
	//         printf("pstart %s\r\n", pstart->name);
	//     }
	//     pstart++;
	// }
}
#endif

int none_probe(struct fpga_dev *dev)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
int none_release(struct fpga_dev *dev)
{
    // printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}

int none_suspend(struct fpga_dev *dev)
{
    return 0;
}
int none_resume(struct fpga_dev *dev)
{
    return 0;
}

int none_start(struct fpga_dev *dev)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
int none_read_frame(struct fpga_dev *dev, unsigned char *otdr_data, unsigned long len, unsigned long *rlen)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
// TODO 开始查询测试结果
// 如果你的编译器不支持bool类型，请定义 typedef unsigned char bool代替，
// 千万不要用unsigned int，否则*val永远返回0
int none_isfinish(struct fpga_dev *dev, bool *val)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
// TODO 停止测试
int none_stop(struct fpga_dev *dev)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
void none_dump(char *fname, unsigned char *data, unsigned long len)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return;
}
int none_version(struct fpga_dev *dev, char *soft_ver, char *hw_ver)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
int none_read_regs(struct fpga_dev *dev, unsigned int base_addr, unsigned int *regs, int len)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
int none_write_regs(struct fpga_dev *dev, unsigned int base_addr, unsigned int *regs, int len)
{
    printf("未实现 %s\r\n", __FUNCTION__);
    return 0;
}
static void __attribute__((constructor(INIT_BSP))) this_init()
{
    struct fpga_if *pif;

    fpga_if_register(&com_if);
    // fpga_if_register(&abc2);
    // fpga_if_register(&abc3);
    // fpga_if_register(&abc4);
    // fpga_if_unregister("this-abc3");
    // pif = fpga_if_append("this-abc2");
    // printf("a %x b %x\r\n", pif->a, pif->b);
    // pif->pfun_read_frame(NULL, NULL, NULL);
    // pif = fpga_if_append("this-abc3");
    // pif->pfun_read_frame(NULL, NULL, NULL);
}
